﻿// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Abp.Authorization;
using Abp.Runtime.Caching;
using Abp.UI;
using CSRedis;
using GCT.Foundation.CacheState.Authorization;
using GCT.Foundation.CacheState.Dtos;
using GCT.Foundation.Configuration;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Yoyo.Abp;
using static GCT.Foundation.GCTConfigs;

namespace GCT.Foundation.CacheState
{
    [AbpAuthorize]
    public class CacheStateAppService : FoundationTemplateAppServiceBase, ICacheStateAppService
    {
        private readonly IServiceProvider _serviceProvider;
        private readonly IConfigurationRoot _appConfiguration;
        private readonly ICacheManager _cacheManager;

        public CacheStateAppService(IServiceProvider serviceProvider,
            IWebHostEnvironment env, 
            ICacheManager cacheManager)
        {
            _serviceProvider = serviceProvider;
            _cacheManager = cacheManager;
            _appConfiguration = env.GetAppConfiguration();
        }

        /// <summary>
        /// 获取全部缓存键
        /// </summary>
        /// <returns></returns>
        /// <exception cref="UserFriendlyException"></exception>
        [AbpAuthorize(CacheStatePermissions.CacheState_Query)]
        public List<GetAllCacheKeyOutput> GetAllCacheKey()
        {
            // 获取默认数据库Id
            var dbId = _appConfiguration.GetValue<int>("Cache:Redis:DatabaseId");

            if (dbId < 0)
            {
                throw new UserFriendlyException(L("RedisConnError"));
            }

            // 获取连接
            var database = GetClient();

            var result = new List<GetAllCacheKeyOutput>();

            // 获取所有Key
            var scan = database.Keys("*");

            var keys = new List<SpiltKey>();
            foreach (var item in scan)
            {
                var keyArr = item.Split(',');
                keys.Add(new SpiltKey() { NKey = keyArr[0], CKey = keyArr[1] });
            }

            var g = keys.GroupBy(x => x.NKey).Select(x => x.Key).ToList();
            foreach (var item in g)
            {
                result.Add(new GetAllCacheKeyOutput()
                {
                    Key = item, CKeys = keys.Where(x => x.NKey == item).Select(x => x.CKey).ToList()
                });
            }

            return result;

        }

        /// <summary>
        /// 获取缓存值
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        [AbpAuthorize(CacheStatePermissions.CacheState_Query)]
        public async Task<string> Get(string key)
        {
            var database = GetClient();
            return await database.GetAsync(key);
        }

        /// <summary>
        /// 删除Key
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        [AbpAuthorize(CacheStatePermissions.CacheState_Delete)]
        public async Task Delete(string key)
        {
            var database = GetClient();
            await database.DelAsync(key);
        }

        /// <summary>
        /// 命名空间删除
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        [AbpAuthorize(CacheStatePermissions.CacheState_Delete)]
        public async Task DeleteNameSpace(string key)
        {
            var database = GetClient();
            var result = GetAllCacheKey();
            foreach (var item in result)
            {
                if (item.Key != key)
                {
                    continue;
                }

                foreach (var cKey in item.CKeys)
                {
                    await database.DelAsync($@"{item.Key},{cKey}");
                }
            }
        }

        /// <summary>
        /// 清空当前数据库
        /// </summary>
        /// <returns></returns>
        [AbpAuthorize(CacheStatePermissions.CacheState_FlushDb)]
        public async Task FlushDb()
        {
            var database = GetClient();

            await database.NodesServerManager.FlushDbAsync();
        }

        /// <summary>
        /// 添加测试缓存数据
        /// </summary>
        /// <returns></returns>
        public async Task AddCacheTest()
        {
            var cache = _cacheManager.GetCache(nameof(CacheStateAppService)).AsTyped<string, string>();
            await cache.SetAsync(nameof(CacheStateAppService), "测试缓存数据");
        }

        /// <summary>
        /// 获取连接
        /// </summary>
        /// <returns></returns>
        private CSRedisClient GetClient()
        {
            // todo 判断是否开启redis

            return _serviceProvider.GetRequiredService<ICSRedisClientProvider>().GetDatabase();
        }
    }
}
